package config

import (
	"database/sql"
	"os"
	"path/filepath"

	"github.com/pkg/errors"
	"gorm.io/driver/sqlite"
	"gorm.io/gorm"
	"gorm.io/gorm/logger"

	"changeme/internal/database"
	"changeme/internal/models"

	// 使用纯Go的SQLite驱动
	_ "modernc.org/sqlite"
)

// GormStorage GORM配置存储实现
type GormStorage struct {
	db *gorm.DB
}

// NewGormStorage 创建GORM存储实例
func NewGormStorage(dbPath string) (*GormStorage, error) {
	// 确保目录存在
	dir := filepath.Dir(dbPath)
	if err := os.MkdirAll(dir, 0755); err != nil {
		return nil, errors.Wrap(err, "failed to create config directory")
	}

	// 连接SQLite数据库 (使用纯Go驱动)
	dsn := dbPath + "?_pragma=foreign_keys(1)&_pragma=journal_mode(WAL)&_pragma=synchronous(NORMAL)&_pragma=temp_store(memory)&_pragma=mmap_size(268435456)"

	// 先打开原生SQL连接以确保使用纯Go驱动
	sqlDB, err := sql.Open("sqlite", dsn)
	if err != nil {
		return nil, errors.Wrap(err, "failed to open sqlite connection")
	}

	// 使用已有的SQL连接创建GORM实例
	db, err := gorm.Open(sqlite.Dialector{
		Conn: sqlDB,
	}, &gorm.Config{
		Logger: logger.Default.LogMode(logger.Silent),
	})
	if err != nil {
		return nil, errors.Wrap(err, "failed to connect to config database")
	}

	storage := &GormStorage{db: db}

	// 自动迁移
	if err := storage.migrate(); err != nil {
		return nil, errors.Wrap(err, "failed to migrate config database")
	}

	return storage, nil
}

// migrate 执行数据库迁移
func (s *GormStorage) migrate() error {
	return s.db.AutoMigrate(&models.DatabaseConfig{})
}

// Save 保存配置
func (s *GormStorage) Save(config *models.DatabaseConfig) error {
	if config.ID == "" {
		if err := config.BeforeCreate(); err != nil {
			return errors.Wrap(err, "failed to generate config ID")
		}
	}

	result := s.db.Create(config)
	if result.Error != nil {
		return errors.Wrap(result.Error, "failed to save config")
	}

	return nil
}

// Get 获取配置
func (s *GormStorage) Get(id string) (*models.DatabaseConfig, error) {
	var config models.DatabaseConfig
	result := s.db.First(&config, "id = ?", id)
	if result.Error != nil {
		if errors.Is(result.Error, gorm.ErrRecordNotFound) {
			return nil, database.ErrConfigNotFound
		}
		return nil, errors.Wrap(result.Error, "failed to get config")
	}

	return &config, nil
}

// GetAll 获取所有配置
func (s *GormStorage) GetAll() ([]*models.DatabaseConfig, error) {
	var configs []*models.DatabaseConfig
	result := s.db.Order("created_at DESC").Find(&configs)
	if result.Error != nil {
		return nil, errors.Wrap(result.Error, "failed to get all configs")
	}

	return configs, nil
}

// Delete 删除配置
func (s *GormStorage) Delete(id string) error {
	result := s.db.Delete(&models.DatabaseConfig{}, "id = ?", id)
	if result.Error != nil {
		return errors.Wrap(result.Error, "failed to delete config")
	}

	if result.RowsAffected == 0 {
		return database.ErrConfigNotFound
	}

	return nil
}

// Update 更新配置
func (s *GormStorage) Update(config *models.DatabaseConfig) error {
	result := s.db.Save(config)
	if result.Error != nil {
		return errors.Wrap(result.Error, "failed to update config")
	}

	return nil
}

// SetDefault 设置默认配置
func (s *GormStorage) SetDefault(id string) error {
	// 开始事务
	tx := s.db.Begin()
	if tx.Error != nil {
		return errors.Wrap(tx.Error, "failed to begin transaction")
	}

	// 清除所有默认标记
	if err := tx.Model(&models.DatabaseConfig{}).Update("is_default", false).Error; err != nil {
		tx.Rollback()
		return errors.Wrap(err, "failed to clear default flags")
	}

	// 设置新的默认配置
	result := tx.Model(&models.DatabaseConfig{}).Where("id = ?", id).Update("is_default", true)
	if result.Error != nil {
		tx.Rollback()
		return errors.Wrap(result.Error, "failed to set default config")
	}

	if result.RowsAffected == 0 {
		tx.Rollback()
		return database.ErrConfigNotFound
	}

	// 提交事务
	if err := tx.Commit().Error; err != nil {
		return errors.Wrap(err, "failed to commit transaction")
	}

	return nil
}

// GetDefault 获取默认配置
func (s *GormStorage) GetDefault() (*models.DatabaseConfig, error) {
	var config models.DatabaseConfig
	result := s.db.First(&config, "is_default = ?", true)
	if result.Error != nil {
		if errors.Is(result.Error, gorm.ErrRecordNotFound) {
			return nil, nil // 没有默认配置不是错误
		}
		return nil, errors.Wrap(result.Error, "failed to get default config")
	}

	return &config, nil
}

// Close 关闭存储
func (s *GormStorage) Close() error {
	sqlDB, err := s.db.DB()
	if err != nil {
		return errors.Wrap(err, "failed to get underlying sql.DB")
	}
	return sqlDB.Close()
}

// GetStats 获取存储统计信息
func (s *GormStorage) GetStats() (map[string]interface{}, error) {
	var count int64
	if err := s.db.Model(&models.DatabaseConfig{}).Count(&count).Error; err != nil {
		return nil, errors.Wrap(err, "failed to count configs")
	}

	var defaultConfig models.DatabaseConfig
	hasDefault := s.db.First(&defaultConfig, "is_default = ?", true).Error == nil

	stats := map[string]interface{}{
		"total_configs": count,
		"has_default":   hasDefault,
	}

	if hasDefault {
		stats["default_config_id"] = defaultConfig.ID
		stats["default_config_name"] = defaultConfig.Name
	}

	return stats, nil
}

// GetConfigsByType 按类型获取配置
func (s *GormStorage) GetConfigsByType(dbType models.DatabaseType) ([]*models.DatabaseConfig, error) {
	var configs []*models.DatabaseConfig
	result := s.db.Where("type = ?", dbType).Order("created_at DESC").Find(&configs)
	if result.Error != nil {
		return nil, errors.Wrap(result.Error, "failed to get configs by type")
	}

	return configs, nil
}

// GetRecentConfigs 获取最近使用的配置
func (s *GormStorage) GetRecentConfigs(limit int) ([]*models.DatabaseConfig, error) {
	var configs []*models.DatabaseConfig
	result := s.db.Where("last_used_at IS NOT NULL").
		Order("last_used_at DESC").
		Limit(limit).
		Find(&configs)
	if result.Error != nil {
		return nil, errors.Wrap(result.Error, "failed to get recent configs")
	}

	return configs, nil
}

// SearchConfigs 搜索配置
func (s *GormStorage) SearchConfigs(keyword string) ([]*models.DatabaseConfig, error) {
	var configs []*models.DatabaseConfig
	result := s.db.Where("name LIKE ? OR host LIKE ? OR database LIKE ?",
		"%"+keyword+"%", "%"+keyword+"%", "%"+keyword+"%").
		Order("created_at DESC").
		Find(&configs)
	if result.Error != nil {
		return nil, errors.Wrap(result.Error, "failed to search configs")
	}

	return configs, nil
}

// ExportConfigs 导出配置（不包含密码）
func (s *GormStorage) ExportConfigs() ([]*models.DatabaseConfig, error) {
	var configs []*models.DatabaseConfig
	result := s.db.Select("id", "name", "type", "host", "port", "username", "database",
		"ssl_mode", "charset", "timezone", "file_path", "options", "is_default",
		"created_at", "updated_at").Find(&configs)
	if result.Error != nil {
		return nil, errors.Wrap(result.Error, "failed to export configs")
	}

	return configs, nil
}

// ImportConfigs 导入配置
func (s *GormStorage) ImportConfigs(configs []*models.DatabaseConfig) error {
	tx := s.db.Begin()
	if tx.Error != nil {
		return errors.Wrap(tx.Error, "failed to begin transaction")
	}

	for _, config := range configs {
		// 生成新的ID
		config.ID = ""
		if err := config.BeforeCreate(); err != nil {
			tx.Rollback()
			return errors.Wrap(err, "failed to generate config ID")
		}

		// 清除默认标记（避免冲突）
		config.IsDefault = false

		if err := tx.Create(config).Error; err != nil {
			tx.Rollback()
			return errors.Wrap(err, "failed to import config")
		}
	}

	if err := tx.Commit().Error; err != nil {
		return errors.Wrap(err, "failed to commit import transaction")
	}

	return nil
}
